// src/adapters/rest_api_adapter.rs

use async_trait::async_trait;
use reqwest::{Client, Method, RequestBuilder, Response};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use anyhow::{Result, anyhow, Context};
use log::{info, warn, error, debug};
use url::Url;
use tokio::time;
use async_recursion::async_recursion;

use crate::{
    interfaces::{DataSourceAdapter, DataSourceConnection},
    models::{
        DataSourceSchema, EntityDefinition, PropertyDefinition, 
        Relationship, MethodDefinition, ParameterDefinition, DataType
    },
    utils::{
        security::{AuthType, SecurityConfig},
        validation::SchemaValidator,
    },
};

/// REST API 适配器 - 支持多种RESTful API数据源
pub struct RestApiAdapter {
    /// HTTP客户端
    client: Client,
    /// API配置
    config: RestApiConfig,
    /// 安全配置
    security_config: SecurityConfig,
    /// 缓存机制
    cache: Option<ApiResponseCache>,
    /// 连接状态
    is_connected: bool,
}

/// REST API 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RestApiConfig {
    /// API基础URL
    pub base_url: String,
    /// API版本
    pub api_version: Option<String>,
    /// 认证类型
    pub auth_type: AuthType,
    /// 请求超时时间（秒）
    pub timeout_secs: u64,
    /// 重试次数
    pub max_retries: u32,
    /// 重试间隔（毫秒）
    pub retry_delay_ms: u64,
    /// 速率限制（请求/秒）
    pub rate_limit: Option<u32>,
    /// 分页配置
    pub pagination: PaginationConfig,
    /// 自定义请求头
    pub custom_headers: HashMap<String, String>,
    /// API文档URL（OpenAPI/Swagger）
    pub api_documentation_url: Option<String>,
}

/// 分页配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginationConfig {
    /// 分页类型
    pub pagination_type: PaginationType,
    /// 页面大小参数名
    pub page_size_param: String,
    /// 页码参数名
    pub page_number_param: String,
    /// 默认页面大小
    pub default_page_size: usize,
    /// 最大页面大小
    pub max_page_size: usize,
}

/// 分页类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaginationType {
    /// 基于页面的分页
    PageBased,
    /// 基于游标的分页
    CursorBased,
    /// 基于偏移量的分页
    OffsetBased,
    /// 无分页
    None,
}

/// API响应缓存
#[derive(Debug, Clone)]
pub struct ApiResponseCache {
    /// 缓存存储
    cache: HashMap<String, (Value, std::time::SystemTime)>,
    /// 缓存过期时间（秒）
    ttl_seconds: u64,
}

/// API端点定义
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiEndpoint {
    /// 端点路径
    pub path: String,
    /// HTTP方法
    pub method: HttpMethod,
    /// 端点描述
    pub description: Option<String>,
    /// 参数定义
    pub parameters: Vec<ApiParameter>,
    /// 响应模式
    pub response_schema: Option<Value>,
    /// 是否需要认证
    pub requires_auth: bool,
}

/// HTTP方法枚举
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HttpMethod {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
    HEAD,
    OPTIONS,
}

/// API参数定义
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiParameter {
    /// 参数名称
    pub name: String,
    /// 参数位置
    pub location: ParameterLocation,
    /// 参数类型
    pub data_type: String,
    /// 是否必需
    pub required: bool,
    /// 默认值
    pub default_value: Option<Value>,
    /// 参数描述
    pub description: Option<String>,
}

/// 参数位置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ParameterLocation {
    Query,
    Path,
    Header,
    Body,
}

/// API资源定义
#[derive(Debug, Clone, Serialize)]
pub struct ApiResource {
    /// 资源名称
    pub name: String,
    /// 资源路径
    pub path: String,
    /// 支持的HTTP方法
    pub supported_methods: Vec<HttpMethod>,
    /// 资源属性
    pub properties: Vec<ApiProperty>,
    /// 子资源
    pub sub_resources: Vec<ApiResource>,
}

/// API属性定义
#[derive(Debug, Clone, Serialize)]
pub struct ApiProperty {
    /// 属性名称
    pub name: String,
    /// 属性类型
    pub data_type: String,
    /// 是否可读
    pub readable: bool,
    /// 是否可写
    pub writable: bool,
    /// 属性描述
    pub description: Option<String>,
}

impl RestApiAdapter {
    /// 创建新的REST API适配器
    pub fn new(config: RestApiConfig) -> Result<Self> {
        let client = Client::builder()
            .timeout(Duration::from_secs(config.timeout_secs))
            .build()
            .map_err(|e| anyhow!("Failed to build HTTP client: {}", e))?;

        let security_config = SecurityConfig::default();
        let cache = Some(ApiResponseCache::new(300)); // 5分钟缓存

        Ok(Self {
            client,
            config,
            security_config,
            cache,
            is_connected: false,
        })
    }

    /// 从OpenAPI/Swagger文档发现API结构
    pub async fn discover_from_openapi(&self, openapi_url: &str) -> Result<Vec<ApiEndpoint>> {
        info!("从OpenAPI文档发现API端点: {}", openapi_url);
        
        let response = self.client.get(openapi_url).send().await?;
        if !response.status().is_success() {
            return Err(anyhow!("OpenAPI文档获取失败: {}", response.status()));
        }

        let openapi_spec: Value = response.json().await?;
        self.parse_openapi_spec(&openapi_spec).await
    }

    /// 解析OpenAPI规范
    async fn parse_openapi_spec(&self, spec: &Value) -> Result<Vec<ApiEndpoint>> {
        let mut endpoints = Vec::new();

        if let Some(paths) = spec.get("paths").and_then(|p| p.as_object()) {
            for (path, path_item) in paths {
                for (method, operation) in self.extract_operations(path_item) {
                    let endpoint = ApiEndpoint {
                        path: path.clone(),
                        method,
                        description: operation.get("description")
                            .and_then(|d| d.as_str())
                            .map(|s| s.to_string()),
                        parameters: self.extract_parameters(operation),
                        response_schema: self.extract_response_schema(operation),
                        requires_auth: self.check_authentication_required(operation),
                    };
                    endpoints.push(endpoint);
                }
            }
        }

        Ok(endpoints)
    }

    /// 从路径项提取操作
    fn extract_operations(&self, path_item: &Value) -> Vec<(HttpMethod, &Value)> {
        let mut operations = Vec::new();
        
        let method_mapping = [
            ("get", HttpMethod::GET),
            ("post", HttpMethod::POST),
            ("put", HttpMethod::PUT),
            ("patch", HttpMethod::PATCH),
            ("delete", HttpMethod::DELETE),
        ];

        for (method_str, method) in method_mapping.iter() {
            if let Some(operation) = path_item.get(*method_str) {
                operations.push((method.clone(), operation));
            }
        }

        operations
    }

    /// 提取参数定义
    fn extract_parameters(&self, operation: &Value) -> Vec<ApiParameter> {
        let mut parameters = Vec::new();

        if let Some(params) = operation.get("parameters").and_then(|p| p.as_array()) {
            for param in params {
                let parameter = ApiParameter {
                    name: param.get("name")
                        .and_then(|n| n.as_str())
                        .unwrap_or("unknown")
                        .to_string(),
                    location: param.get("in")
                        .and_then(|loc| loc.as_str())
                        .map(|loc| match loc {
                            "query" => ParameterLocation::Query,
                            "path" => ParameterLocation::Path,
                            "header" => ParameterLocation::Header,
                            "body" => ParameterLocation::Body,
                            _ => ParameterLocation::Query,
                        })
                        .unwrap_or(ParameterLocation::Query),
                    data_type: param.get("schema")
                        .and_then(|s| s.get("type"))
                        .and_then(|t| t.as_str())
                        .unwrap_or("string")
                        .to_string(),
                    required: param.get("required")
                        .and_then(|r| r.as_bool())
                        .unwrap_or(false),
                    default_value: param.get("default").cloned(),
                    description: param.get("description")
                        .and_then(|d| d.as_str())
                        .map(|s| s.to_string()),
                };
                parameters.push(parameter);
            }
        }

        parameters
    }

    /// 提取响应模式
    fn extract_response_schema(&self, operation: &Value) -> Option<Value> {
        operation.get("responses")?
            .get("200")?
            .get("content")?
            .get("application/json")?
            .get("schema")
            .cloned()
    }

    /// 检查是否需要认证
    fn check_authentication_required(&self, operation: &Value) -> bool {
        operation.get("security")
            .and_then(|s| s.as_array())
            .map(|arr| !arr.is_empty())
            .unwrap_or(false)
    }

    /// 执行API请求
    pub async fn execute_request(&self, endpoint: &ApiEndpoint, params: &HashMap<String, Value>) -> Result<Value> {
        let url = self.build_url(&endpoint.path, params)?;
        let mut request = self.build_request(&endpoint.method, &url)?;
        
        request = self.add_headers(request, endpoint);
        request = self.add_parameters(request, endpoint, params)?;
        request = self.add_authentication(request, endpoint)?;

        self.execute_request_with_retry(request, endpoint).await
    }

    /// 构建完整URL
    fn build_url(&self, path: &str, params: &HashMap<String, Value>) -> Result<Url> {
        let mut url = Url::parse(&self.config.base_url)?;
        url.set_path(path);
        
        // 添加路径参数
        let mut path_segments: Vec<String> = url.path_segments()
            .map(|segments| segments.map(|s| s.to_string()).collect())
            .unwrap_or_default();
            
        for (key, value) in params {
            if let Some(value_str) = value.as_str() {
                let placeholder = format!("{{{}}}", key);
                if let Some(segment) = path_segments.iter_mut().find(|s| s.contains(&placeholder)) {
                    *segment = segment.replace(&placeholder, value_str);
                }
            }
        }
        
        url.set_path(&path_segments.join("/"));
        Ok(url)
    }

    /// 构建请求
    fn build_request(&self, method: &HttpMethod, url: &Url) -> Result<RequestBuilder> {
        let request = match method {
            HttpMethod::GET => self.client.get(url.as_str()),
            HttpMethod::POST => self.client.post(url.as_str()),
            HttpMethod::PUT => self.client.put(url.as_str()),
            HttpMethod::PATCH => self.client.patch(url.as_str()),
            HttpMethod::DELETE => self.client.delete(url.as_str()),
            HttpMethod::HEAD => self.client.head(url.as_str()),
            HttpMethod::OPTIONS => self.client.request(reqwest::Method::OPTIONS, url.as_str()),
        };
        
        Ok(request)
    }

    /// 添加请求头
    fn add_headers(&self, request: RequestBuilder, endpoint: &ApiEndpoint) -> RequestBuilder {
        let mut request = request;
        
        // 添加自定义请求头
        for (key, value) in &self.config.custom_headers {
            request = request.header(key, value);
        }
        
        // 添加内容类型头
        if matches!(endpoint.method, HttpMethod::POST | HttpMethod::PUT | HttpMethod::PATCH) {
            request = request.header("Content-Type", "application/json");
        }
        
        request
    }

    /// 添加参数
    fn add_parameters(&self, request: RequestBuilder, endpoint: &ApiEndpoint, params: &HashMap<String, Value>) -> Result<RequestBuilder> {
        let mut request = request;
        
        for param in &endpoint.parameters {
            if let Some(value) = params.get(&param.name) {
                match param.location {
                    ParameterLocation::Query => {
                        if let Some(value_str) = value.as_str() {
                            request = request.query(&[(param.name.as_str(), value_str)]);
                        }
                    }
                    ParameterLocation::Path => {
                        // 路径参数已经在URL构建时处理
                    }
                    ParameterLocation::Header => {
                        if let Some(value_str) = value.as_str() {
                            request = request.header(&param.name, value_str);
                        }
                    }
                    ParameterLocation::Body => {
                        if matches!(endpoint.method, HttpMethod::POST | HttpMethod::PUT | HttpMethod::PATCH) {
                            request = request.json(value);
                        }
                    }
                }
            }
        }
        
        Ok(request)
    }

    /// 添加认证
    fn add_authentication(&self, request: RequestBuilder, endpoint: &ApiEndpoint) -> Result<RequestBuilder> {
        if !endpoint.requires_auth {
            return Ok(request);
        }
        
        let request = match self.security_config.auth_type {
            AuthType::BearerToken => {
                if let Some(token) = &self.security_config.bearer_token {
                    request.bearer_auth(token)
                } else {
                    request
                }
            }
            AuthType::ApiKey => {
                if let Some(api_key) = &self.security_config.api_key {
                    request.header(&self.security_config.api_key_header, api_key)
                } else {
                    request
                }
            }
            AuthType::BasicAuth => {
                if let (Some(username), Some(password)) = (
                    &self.security_config.username,
                    &self.security_config.password
                ) {
                    request.basic_auth(username, Some(password))
                } else {
                    request
                }
            }
            AuthType::OAuth2 => {
                // OAuth2认证需要更复杂的处理
                request
            }
            AuthType::None => request,
        };
        
        Ok(request)
    }

    /// 带重试的请求执行
    async fn execute_request_with_retry(&self, request: RequestBuilder, endpoint: &ApiEndpoint) -> Result<Value> {
        let mut last_error = None;
        
        for attempt in 0..=self.config.max_retries {
            match request.try_clone().unwrap().send().await {
                Ok(response) => {
                    if response.status().is_success() {
                        return self.process_response(response, endpoint).await;
                    } else if response.status().is_server_error() && attempt < self.config.max_retries {
                        warn!("服务器错误，准备重试: {}", response.status());
                        time::sleep(Duration::from_millis(self.config.retry_delay_ms)).await;
                        continue;
                    } else {
                        return Err(anyhow!("API请求失败: {}", response.status()));
                    }
                }
                Err(e) => {
                    last_error = Some(e);
                    if attempt < self.config.max_retries {
                        time::sleep(Duration::from_millis(self.config.retry_delay_ms)).await;
                    }
                }
            }
        }
        
        Err(anyhow!("所有重试尝试均失败: {:?}", last_error))
    }

    /// 处理API响应
    async fn process_response(&self, response: Response, endpoint: &ApiEndpoint) -> Result<Value> {
        let content_type = response.headers()
            .get("content-type")
            .and_then(|ct| ct.to_str().ok())
            .unwrap_or("application/json");
            
        match content_type {
            "application/json" => {
                let json_value: Value = response.json().await?;
                Ok(json_value)
            }
            "application/xml" | "text/xml" => {
                let xml_text = response.text().await?;
                self.parse_xml_response(&xml_text).await
            }
            "text/csv" => {
                let csv_text = response.text().await?;
                self.parse_csv_response(&csv_text).await
            }
            _ => {
                let text = response.text().await?;
                Ok(Value::String(text))
            }
        }
    }

    /// 解析XML响应
    async fn parse_xml_response(&self, xml_text: &str) -> Result<Value> {
        // 简化实现，实际应使用XML解析库
        Ok(Value::String(xml_text.to_string()))
    }

    /// 解析CSV响应
    async fn parse_csv_response(&self, csv_text: &str) -> Result<Value> {
        let mut rdr = csv::Reader::from_reader(csv_text.as_bytes());
        let mut records = Vec::new();
        
        for result in rdr.deserialize() {
            let record: HashMap<String, String> = result?;
            records.push(Value::Object(
                record.into_iter()
                    .map(|(k, v)| (k, Value::String(v)))
                    .collect()
            ));
        }
        
        Ok(Value::Array(records))
    }

    /// 从API响应推断数据结构
    fn infer_data_structure(&self, response: &Value, endpoint: &ApiEndpoint) -> Result<ApiResource> {
        let mut resource = ApiResource {
            name: endpoint.path.split('/').last().unwrap_or("resource").to_string(),
            path: endpoint.path.clone(),
            supported_methods: vec1[endpoint.method.clone()],
            properties: Vec::new(),
            sub_resources: Vec::new(),
        };

        self.extract_properties_from_response(response, &mut resource.properties);
        Ok(resource)
    }

    /// 从响应中提取属性
    fn extract_properties_from_response(&self, response: &Value, properties: &mut Vec<ApiProperty>) {
        if let Value::Object(obj) = response {
            for (key, value) in obj {
                let data_type = match value {
                    Value::Null => "null",
                    Value::Bool(_) => "boolean",
                    Value::Number(n) => if n.is_f64() { "float" } else { "integer" },
                    Value::String(_) => "string",
                    Value::Array(_) => "array",
                    Value::Object(_) => "object",
                };

                let property = ApiProperty {
                    name: key.clone(),
                    data_type: data_type.to_string(),
                    readable: true,
                    writable: matches!(data_type, "POST" | "PUT" | "PATCH"),
                    description: Some(format!("类型: {}", data_type)),
                };
                
                properties.push(property);
            }
        }
    }
}

#[async_trait]
impl DataSourceAdapter for RestApiAdapter {
    /// 连接REST API数据源
    async fn connect(&self, _data_source_type: &str, connection_string: &str) 
        -> Result<Box<dyn DataSourceConnection>> 
    {
        info!("连接REST API数据源: {}", connection_string);
        
        // 验证连接
        let health_url = format!("{}/health", self.config.base_url);
        let response = self.client.get(&health_url).send().await?;
        
        if !response.status().is_success() {
            return Err(anyhow!("REST API健康检查失败: {}", response.status()));
        }
        
        let connection = RestApiConnection {
            client: self.client.clone(),
            config: self.config.clone(),
            is_connected: true,
        };
        
        info!("REST API连接成功");
        Ok(Box::new(connection))
    }

    /// 提取API Schema
    async fn extract_schema(&self) -> Result<DataSourceSchema> {
        info!("开始提取REST API Schema...");
        
        let endpoints = if let Some(doc_url) = &self.config.api_documentation_url {
            self.discover_from_openapi(doc_url).await?
        } else {
            self.discover_endpoints_heuristically().await?
        };
        
        info!("发现 {} 个API端点", endpoints.len());
        
        let entities = self.endpoints_to_entities(&endpoints).await?;
        let relationships = self.discover_relationships(&endpoints).await?;
        let methods = self.endpoints_to_methods(&endpoints);
        
        let schema = DataSourceSchema {
            entities,
            relationships,
            methods,
            metadata: HashMap::from([
                ("api_base_url".to_string(), self.config.base_url.clone().into()),
                ("endpoint_count".to_string(), endpoints.len().into()),
                ("discovery_method".to_string(), 
                    if self.config.api_documentation_url.is_some() { 
                        "openapi".into() 
                    } else { 
                        "heuristic".into() 
                    }
                ),
            ]),
        };
        
        info!("REST API Schema提取完成");
        Ok(schema)
    }

    /// 测试连接
    async fn test_connection(&self) -> Result<bool> {
        let health_url = format!("{}/health", self.config.base_url);
        match self.client.get(&health_url).send().await {
            Ok(response) => Ok(response.status().is_success()),
            Err(_) => Ok(false),
        }
    }

    /// 获取支持的数据源类型
    fn get_supported_data_sources(&self) -> Vec<String> {
        vec![
            "REST".to_string(),
            "HTTP".to_string(),
            "JSON API".to_string(),
            "OpenAPI".to_string(),
        ]
    }
}

/// REST API连接实现
pub struct RestApiConnection {
    client: Client,
    config: RestApiConfig,
    is_connected: bool,
}

#[async_trait]
impl DataSourceConnection for RestApiConnection {
    async fn open(&mut self) -> Result<()> {
        if self.is_connected {
            return Ok(());
        }
        
        // 测试连接
        let health_url = format!("{}/health", self.config.base_url);
        let response = self.client.get(&health_url).send().await?;
        
        if !response.status().is_success() {
            return Err(anyhow!("REST API连接失败"));
        }
        
        self.is_connected = true;
        info!("REST API连接已建立");
        Ok(())
    }
    
    async fn close(&mut self) -> Result<()> {
        self.is_connected = false;
        info!("REST API连接已关闭");
        Ok(())
    }
    
    fn is_connected(&self) -> bool {
        self.is_connected
    }
    
    async fn query_data(&self, query: &str) -> Result<Vec<Value>> {
        // 将查询解析为API请求
        let url = format!("{}{}", self.config.base_url, query);
        let response = self.client.get(&url).send().await?;
        
        if !response.status().is_success() {
            return Err(anyhow!("API查询失败: {}", response.status()));
        }
        
        let json_value: Value = response.json().await?;
        Ok(vec![json_value])
    }
}


// API响应缓存实现
impl ApiResponseCache {
    pub fn new(ttl_seconds: u64) -> Self {
        Self {
            cache: HashMap::new(),
            ttl_seconds,
        }
    }
    
    pub fn get(&self, key: &str) -> Option<&Value> {
        self.cache.get(key)
            .and_then(|(value, timestamp)| {
                if timestamp.elapsed().unwrap_or_default().as_secs() < self.ttl_seconds {
                    Some(value)
                } else {
                    None
                }
            })
    }
    
    pub fn set(&mut self, key: String, value: Value) {
        self.cache.insert(key, (value, std::time::SystemTime::now()));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use mockito::{Mock, Server};
    
    #[tokio::test]
    async fn test_rest_api_adapter_creation() {
        let config = RestApiConfig {
            base_url: "https://api.example.com".to_string(),
            api_version: Some("v1".to_string()),
            auth_type: AuthType::None,
            timeout_secs: 30,
            max_retries: 3,
            retry_delay_ms: 1000,
            rate_limit: Some(100),
            pagination: PaginationConfig {
                pagination_type: PaginationType::PageBased,
                page_size_param: "page_size".to_string(),
                page_number_param: "page".to_string(),
                default_page_size: 50,
                max_page_size: 100,
            },
            custom_headers: HashMap::new(),
            api_documentation_url: None,
        };
        
        let adapter = RestApiAdapter::new(config).unwrap();
        assert!(adapter.test_connection().await.is_ok());
    }
    
    #[tokio::test]
    async fn test_api_request_execution() {
        let mut server = Server::new_async().await;
        let mock = server.mock("GET", "/api/test")
            .with_status(200)
            .with_body(r#"{"message": "success"}"#)
            .create_async()
            .await;
            
        let config = RestApiConfig {
            base_url: server.url(),
            api_version: None,
            auth_type: AuthType::None,
            timeout_secs: 30,
            max_retries: 3,
            retry_delay_ms: 1000,
            rate_limit: None,
            pagination: PaginationConfig::default(),
            custom_headers: HashMap::new(),
            api_documentation_url: None,
        };
        
        let adapter = RestApiAdapter::new(config).unwrap();
        let endpoint = ApiEndpoint {
            path: "/api/test".to_string(),
            method: HttpMethod::GET,
            description: None,
            parameters: Vec::new(),
            response_schema: None,
            requires_auth: false,
        };
        
        let result = adapter.execute_request(&endpoint, &HashMap::new()).await;
        assert!(result.is_ok());
        
        mock.assert_async().await;
    }
}